package com.huida.app.commonusage;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultiset;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangzhuangzhuang
 * @DESC:
 * @date 2022-02-17 13:05
 */
@SpringBootTest
@Slf4j
public class CommonTestDemo {

	/**
	 * List集合拼接成以逗号分隔的字符串
	 * */
	@Test
	public void test01(){
		// 把List集合拼接成以逗号分割的字符串 a,b,c
		List<String> data = Arrays.asList("a", "b", "c");
		// 第一种方法可以用stream流
		String joinedData = data.stream().collect(Collectors.joining(",")); // joinedData: a,b,c
		log.info("joinedData: {}", joinedData);

		// 第二种方法 String类存在join方法实现该功能
		String joinedInfo = String.join(",", data);
		log.info("joinedInfo: {}", joinedInfo); // joinedInfo: a,b,c
	}

	/**
	 * 比较两个字符串是否相等，忽略大小写
	 **/
	@Test
	public void test02(){
		String str01 = "Hello World";
		String str02 = "hello world";
		log.info("{}", str01.equalsIgnoreCase(str02) ? "相等" : "不相等"); // 相等
	}

	/**
	 * 比较两个对象是否相等 Objects.equals(strA, strB)
	 * 当使用equals比较两个对象是否相等的时候，还需要对左边的对象进行判空，不然可能会报空指针异常
	 * eg: 用java.util包下Objects封装好的比较是否相等的方法
	 * */
	@Test
	public void test03(){
		String strA = "hello world";
		String strB = "Hello World";
		log.info("Objects.equals(strA, strB), {}", Objects.equals(strA, strB)); // false
	}

	/**
	 * isEmpty  str.length == 0 && str == null
	 * isBlank str.length == 0 && str == null && str == ""
	 * */
	@Test
	public void test04(){
		String str01 = " ";
		log.info("StringUtils.isEmpty(str01): {}", StringUtils.isEmpty(str01)); // false
		log.info("StringUtils.isBlank(str01): {}", StringUtils.isBlank(str01)); // true

		String str02 = null;
		log.info("StringUtils.isEmpty(str02): {}", StringUtils.isEmpty(str02)); // true
		log.info("StringUtils.isBlank(str02): {}", StringUtils.isBlank(str02)); // true\
	}

	// 求交集
	@Test
	public void test05(){
		ArrayList<String> data01 = new ArrayList<>();
		data01.add("a");
		data01.add("b");
		data01.add("c");
		ArrayList<String> data02 = new ArrayList<>();
		data02.add("a");
		data02.add("b");
		data02.add("d");
		data01.retainAll(data02);
		log.info("===》 {}", ArrayUtils.toString(data01)); // ===》 [a, b]
	}

	// 求差集
	@Test
	public void test06(){
		ArrayList<String> data01 = new ArrayList<>();
		data01.add("a");
		data01.add("b");
		data01.add("c");
		ArrayList<String> data02 = new ArrayList<>();
		data02.add("a");
		data02.add("b");
		data02.add("d");
		data01.removeAll(data02);
		log.info("===》 {}", ArrayUtils.toString(data01)); // ===》 [c] (data01有的data02没有的）
	}

	// 求并集
	@Test
	public void test07(){
		ArrayList<String> data01 = new ArrayList<>();
		data01.add("a");
		data01.add("b");
		data01.add("c");
		ArrayList<String> data02 = new ArrayList<>();
		data02.add("a");
		data02.add("b");
		data02.add("d");
		data01.addAll(data02);
		List<String> allData = data01.stream().distinct().collect(Collectors.toList());
		log.info("===》 {}", ArrayUtils.toString(allData)); // ===》 [a, b, c, d]
	}

	/**
	 * 集合去并集、交集、差集的替代性写法
	 * - 取交集：
	 *      Collection<String> collect01 = CollectionUtils.retainAll(listA, listB);
	 * - 取并集：
	 *      Collection<String> collect02 = CollectionUtils.union(listA, listB);
	 * - 取差集
	 *      Collection<String> collect03 = CollectionUtils.subtract(listA, listB);
	 * */

	/**
	 * 重复拼接字符串
	 * */
	@Test
	public void test08(){
		String info = StringUtils.repeat("info", 3);
		log.info("==》: " + info); // ==》: infoinfoinfo
	}

	// ===== ★黑科技集合★ =====
	/**
	 * Multimap 一个key可以映射多个value的HashMap
	 *
	 * 引入：
	 * <dependency>
	 *     <groupId>com.google.guava</groupId>
	 *     <artifactId>guava</artifactId>
	 *     <version>30.1.1-jre</version>
	 * </dependency>
	 * */
	@Test
	public void test09(){
		ArrayListMultimap<String, Integer> map = ArrayListMultimap.create();
		map.put("key", 1);
		map.put("key", 2);
		Collection<Integer> values = map.get("key");
		log.info("map: {}", Objects.toString(map)); // map: {key=[1, 2]}
		log.info("values: {}", Objects.toString(values)); // values: [1, 2]
	}

	/**
	 * BiMap一种连value也不能重复的HashMap
	 **/
	@Test
	public void test10(){
		BiMap<String, String> biMap = HashBiMap.create();
		// 如果value重复，put方法会抛出异常，除非使用forcePut方法
		biMap.put("key", "value");
		log.info("biMap: {}", Objects.toString(biMap)); // biMap: {key=value}
		// 既然value不能重复，何不实现翻转key/value的方法
		BiMap<String, String> inverseBiMap = biMap.inverse();
		log.info("inverseBiMap: {}", inverseBiMap); // inverseBiMap: {value=key}
	}

	/**
	 * Multiset一种用来计数的Set
	 * */
	@Test
	public void test11(){
		HashMultiset<String> multiset = HashMultiset.create();
		multiset.add("apple");
		multiset.add("apple");
		multiset.add("orange");
		multiset.add("orange");
		multiset.add("orange");
		multiset.add("watermelon");
		// 统一指定元素个数
		log.info("multiset.count('apple'), {}", multiset.count("apple")); // multiset.count('apple'), 2
		// 查看去重元素
		Set<String> distinctSet = multiset.elementSet(); // 查看去重的元素
		log.info("distinctSet: {}", distinctSet); // distinctSet: [orange, apple, watermelon]
		// 手动设置某个元素出现的次数
		multiset.setCount("CHN", 5);
		log.info("multiSet: {}", Objects.toString(multiset)); // multiSet: [orange x 3, apple x 2, CHN x 5, watermelon]
	}
}